IAMポリシーの直接アタッチを調査するLambdaFunctionをつくってみた
ご機嫌いかがでしょうか、豊崎です。
今回、IAMユーザの権限について調査を行うLambdaFunctionを作成したので、ご紹介させていただきます。
前提
ここではIAMポリシーの管理ルールとして以下の前提条件があるとします。
- IAMユーザへの直接のポリシー付与は認められていない
- IAMグループからの権限付与のみを許可している
準備
以下表のIAMユーザ、グループを作成しました。
ユーザ | IAMグループ | インラインポリシー | AWS管理ポリシー |
demo-user01 | demo-group | あり | なし |
demo-user02 | demo-group | なし | あり |
demo-user03 | - | あり | あり |
demo-user04 | demo-group | なし | なし |
また、通知用のSNSTopicは別途作成をしています。
LambdaFunctionの動作
全てのIAMユーザに対して以下をチェックする
- IAMユーザ自体にインラインポリシーがアタッチされていないこと
- IAMユーザ自体にAWS管理ポリシーがアタッチされていないこと
- IAMユーザがIAMグループに所属していること(野良ユーザじゃないこと)
上記に該当するIAMユーザがいた場合にはSNS通知を行う。 *demo-user01,02,03が該当するため、検知される想定です。
LambdaFunction
言語:Python3.6 タイムアウト:1分
import boto3 c_iam = boto3.client('iam') r_iam = boto3.resource('iam') sns = boto3.client('sns') def check_inline(list_names): list_inline_policy_user = [] for name in list_names: list_inline_policy = [] user = r_iam.User(name) inline_policy = user.policies.all() for policy in user.policies.all(): list_inline_policy.append(policy.name) if len(list_inline_policy) > 0: list_inline_policy_user.append(name) return list_inline_policy_user def check_managed(list_names): list_managed_policy_user = [] for name in list_names: list_managed_policy = [] user = r_iam.User(name) for managed_policy in user.attached_policies.all(): list_managed_policy.append(managed_policy.policy_name) if len(list_managed_policy) > 0: list_managed_policy_user.append(name) return list_managed_policy_user def check_solo(list_names): list_solo_user = [] for name in list_names: user = c_iam.list_groups_for_user(UserName=name) if len(user['Groups']) == 0: list_solo_user.append(name) return list_solo_user def sns_publish(list_inline_policy_user,list_managed_policy_user,list_solo_user): mes = f" IAMユーザに問題が見つかりました。\n\ 内容を確認して修正してください。\n\n\n\ インラインポリシーが設定されているIAMユーザ:{list_inline_policy_user}\n\ AWS管理ポリシーが設定されているIAMユーザ:{list_managed_policy_user}\n\ IAMグループに所属していないIAMユーザ:{list_solo_user}\n" sns.publish( TopicArn='arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:demo-sns', Message=mes, Subject="IAM User's rule violation." ) def lambda_handler(event,context): # IAMユーザの一覧を取得 list_users = c_iam.list_users() list_names = [user_name['UserName'] for user_name in list_users['Users']] # IAMユーザ自体にインラインポリシーがアタッチされていないことをcheck list_inline_policy_user = check_inline(list_names) # IAMユーザ自体にAWS管理ポリシーがアタッチされていないことをcheck! list_managed_policy_user = check_managed(list_names) # IAMユーザがIAMグループに所属していること(野良ユーザじゃないこと)をchek! list_solo_user = check_solo(list_names) # 問題があった時にSNSで通知 sns_publish(list_inline_policy_user,list_managed_policy_user,list_solo_user) response = { "UserWithInlinePolicy": list_inline_policy_user, "UserWithManagedPolicy": list_managed_policy_user, "SoloUser": list_solo_user } return response
結果の出力とSNS通知
結果としては無事想定の通りに出力されました。
{ "UserWithInlinePolicy": [ "demo-user01", "demo-user03" ], "UserWithManagedPolicy": [ "demo-user02", "demo-user03" ], "SoloUser": [ "demo-user03" ] }
該当のIAMユーザがいたため、SNSの通知も送信されています。
さいごに
IAMユーザ毎に、ポリシーをアタッチすることは可能ですが管理が煩雑になりがちです。 可能であればIAMグループ経由でポリシーの付与を行う方が綺麗に管理できることが多いです。 本記事には前提がありますが、似た環境であれば少し修正して活用いただけるのではないかと思います。 誰かのお役に立てば幸いです。